home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2007 December
/
PCWKCD1207B.iso
/
Blogowanie poza sfera
/
Flock 0.9.1.3 stable
/
flock-0.9.1.3.en-US.win32.exe
/
flock
/
components
/
flockFlickrService.js
< prev
next >
Wrap
Text File
|
2007-10-12
|
95KB
|
2,850 lines
// vim: ts=2 sw=2 expandtab cindent
//
// BEGIN FLOCK GPL
//
// Copyright Flock Inc. 2005-2007
// http://flock.com
//
// This file may be used under the terms of of the
// GNU General Public License Version 2 or later (the "GPL"),
// http://www.gnu.org/licenses/gpl.html
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// END FLOCK GPL
//
const ENABLE_DEBUG = true; // switch to turn off slow debug code for production
function DEBUG(x) { if (ENABLE_DEBUG) debug("flockFlickrService: "+x+"\n"); }
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
const FLICKR_TITLE = "Flickr Web Service";
const FLICKR_FAVICON = "http://www.flickr.com/favicon.ico";
const FLICKR_CID = Components.ID("{db720a5c-6315-49bf-a39f-b4d4aa5ed142}");
const FLICKR_CONTRACTID = "@flock.com/?photo-api-flickr;1";
const SERVICE_ENABLED_PREF = "flock.service.flickr.enabled";
const CATEGORY_COMPONENT_NAME = "Flickr JS Component"
const CATEGORY_ENTRY_NAME = "flickr"
const flockIError = Components.interfaces.flockIError;
const flockIPhoto = Components.interfaces.flockIPhoto;
const flockIPhotoAccount = Components.interfaces.flockIPhotoAccount;
const flockIPhotoAlbum = Components.interfaces.flockIPhotoAlbum;
const flockIPhotoAPI = Components.interfaces.flockIPhotoAPI;
const flockIPhotoPerson = Components.interfaces.flockIPhotoPerson;
const FLOCK_PHOTO_CONTRACTID = "@flock.com/photo;1";
const FLOCK_PHOTOPERSON_CONTRACTID = "@flock.com/photo-person;1";
const FLOCK_PHOTO_ALBUM_CONTRACTID = "@flock.com/photo-album;1";
const FLOCK_PHOTO_ACCOUNT_CONTRACTID = "@flock.com/photo-account;1";
const FLOCK_ERROR_CONTRACTID = "@flock.com/error;1";
const PHOTOAPIMGR_CONTRACTID = "@flock.com/photo-api-manager;1?";
const RDFS = Components.classes["@mozilla.org/rdf/rdf-service;1"]
.getService(Components.interfaces.nsIRDFService);
var gCompTK;
function getCompTK() {
if (!gCompTK) {
gCompTK = Components.classes["@flock.com/singleton;1"]
.getService(Components.interfaces.flockISingleton)
.getSingleton("chrome://browser/content/flock/services/common/load-compTK.js")
.wrappedJSObject;
}
return gCompTK;
}
var gTimers = []; // For use with the scheduler
function Namespace(ns) { return function (arg) { return RDFS.GetResource (ns+arg); } }
const FLRDF = Namespace("http://flock.com/rdf#");
const FLICKR_STRING_BUNDLE = "chrome://flock/locale/services/flickr/flickr.properties";
// String defaults... may be updated later through Web Detective
var gStrings = {
"domains": "flickr.com,yahoo.com",
"userlogin": "http://flickr.com/signin/",
"privatemessage": "http://www.flickr.com/messages_write.gne",
"userprofile": "http://www.flickr.com/people/%accountid%/",
"editprofile": "http://www.flickr.com/profile_edit.gne",
"relationship": "http://www.flickr.com/relationship.gne?id=%accountid%",
"userphotos": "http://www.flickr.com/photos/%accountid%/",
"photopage": "http://www.flickr.com/photos/%accountid%/%photoid%/",
"commentsreceivedRSS": "http://api.flickr.com/services/feeds/activity.gne?id=%accountid%&format=rss_200",
"commentrepliesRSS": "http://api.flickr.com/services/feeds/photos_comments.gne?user_id=%accountid%&format=rss_200",
"staticimage": "http://static.flickr.com/%server%/%photoid%_%secret%%size%.jpg"
};
function flickrPhoto() {
}
flickrPhoto.prototype= {
id: "",
thumbnail: "",
webPageUrl: "",
midSizePhoto: "",
largeSizePhoto: "",
title: "",
username: "",
userid: "",
is_public: "true",
is_video: "false",
svcShortName: 'flickr',
buildTooltip: function( ) {
// do we have to use document from the window to ceate elements? -- ja
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow('navigator:browser');
if (!win) return null;
var hbox = win.document.createElement('hbox');
var img = win.document.createElement('image');
img.setAttribute('src', this.icon );
hbox.appendChild(img);
var box = win.document.createElement('vbox');
box.setAttribute('style', 'max-width: 250px');
var title = win.document.createElement('label');
title.setAttribute('value', this.title );
title.setAttribute('crop', 'end');
box.appendChild(title);
var lbl = win.document.createElement('label');
lbl.setAttribute('value', this.username );
lbl.setAttribute('class', 'user');
box.appendChild(lbl);
hbox.appendChild(box)
var vbox = win.document.createElement('vbox');
var cbox = win.document.createElement('hbox');
var largeImg = win.document.createElement('image');
largeImg.setAttribute('src', this.midSizePhoto);
largeImg.setAttribute('style', 'margin-bottom: 2px;');
var spacer = win.document.createElement('spacer');
spacer.setAttribute('flex', '1');
cbox.appendChild(largeImg);
cbox.appendChild(spacer);
vbox.appendChild(cbox);
vbox.appendChild(hbox);
return vbox;
},
buildHTML: function( ) {
return '<a title="'+this.title+'" href="'+this.webPageUrl+'"><img src="'+this.midSizePhoto+'" border="0" /></a>';
},
buildLargeHTML: function( ) {
return '<a title="'+this.title+'" href="'+this.webPageUrl+'"><img src="'+this.largeSizePhoto+'" border="0" /></a>';
},
buildBBCode: function ( ) {
return '[url=' + this.webPageUrl + '][img]'+ this.largeSizePhoto +'[/img][/url]';
},
QueryInterface: function(iid) {
if (!iid.equals(Components.interfaces.nsISupports) &&
!iid.equals(Components.interfaces.flockIPhoto)) {
throw Components.results.NS_ERROR_NO_INTERFACE;
}
return this;
}
};
// ====================================================
// ========== BEGIN General helper functions ==========
// ====================================================
function loadSubScript(spec)
{
var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader);
var context = {};
loader.loadSubScript(spec, context);
return context;
}
function loadLibraryFromSpec(aSpec)
{
var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript(aSpec);
}
loadSubScript("chrome://browser/content/utilityOverlay.js");
loadLibraryFromSpec("chrome://browser/content/flock/common/flocksafe.js");
loadLibraryFromSpec("chrome://browser/content/flock/common/md5.js");
loadLibraryFromSpec("chrome://browser/content/flock/photo/photoAPI.js");
function flock_flickrBuildPhotoUrl(server, id, secret, size)
{
var convertedSize = "";
switch (size) {
case "square": convertedSize = "_s"; break;
case "thumbnail": convertedSize = "_t"; break;
case "small": convertedSize = "_m"; break;
case "medium": convertedSize = "_d"; break;
case "large": convertedSize = "_b"; break;
case "original": convertedSize = "_o"; break;
default: convertedSize = "";
}
return gStrings["staticimage"].replace("%server%", server)
.replace("%photoid%", id)
.replace("%secret%", secret)
.replace("%size%", convertedSize);
}
function flock_flickrBuildPageUrl(aUserID, aPhotoID) {
return gStrings["photopage"].replace("%accountid%", aUserID).replace("%photoid%", aPhotoID);
}
// refresh the mediabar if it is open and contains private media
function flock_refreshMediabarIfHasPrivate() {
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow("navigator:browser");
// if the mediabar is open
if (win &&
win.document.getElementById("mediabar") &&
win.document.getElementById("mediabar").getAttribute("hidden") != "true" &&
win.TopbarJSCtx().gPhotoDrawer &&
win.TopbarJSCtx().gPhotoDrawer.mHasPrivateMedia)
{
win.TopbarJSCtx().gPhotoDrawer.refreshView();
}
}
// ===============================================
// ========== BEGIN flickrService class ==========
// ===============================================
function flickrService()
{
this.obs = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
this.state = flockIPhotoAPI.LOGGED_OUT;
this.acUtils = Components.classes["@flock.com/account-utils;1"]
.getService(Components.interfaces.flockIAccountUtils);
this.url = "http://www.flickr.com";
this.mIsInitialized = false;
this._ctk = {
interfaces: [
"nsISupports",
"nsIClassInfo",
"nsISupportsCString",
"nsIObserver",
"flockIPhotoAPI",
"flockIPollingService",
//"flockIPeopleActionController",
"flockIWebService",
"flockIAuthenticateNewAccount",
"flockIManageableWebService",
"flockIMediaWebService",
"flockISocialWebService",
],
shortName: "flickr",
fullName: "Flickr",
description: FLICKR_TITLE,
favicon: FLICKR_FAVICON,
CID: FLICKR_CID,
contractID: FLICKR_CONTRACTID,
accountClass: flickrAccount,
needPassword: false
};
this._logger = Cc['@flock.com/logger;1'].createInstance(Ci.flockILogger);
this._logger.init('flickr');
this._profiler = Cc["@flock.com/profiler;1"].getService(Ci.flockIProfiler);
this.init();
}
// BEGIN nsIObserver interface
flickrService.prototype.observe =
function flickrService_observe(aSubject, aTopic, aData)
{
switch (aTopic) {
case "new-feed-items":
{
aSubject.QueryInterface(Components.interfaces.flockIFeed);
var uri = aSubject.getURL();
if (uri.host == "flickr.com" || (uri.host.indexOf(".flickr.com") > 0)) {
if (this.acUtils.activatedAccountExists(this.urn)) {
this._handleCommentNotifications(aSubject);
}
}
}; break;
}
}
// END nsIObserver interface
flickrService.prototype._handleCommentNotifications =
function flickrService_handleCommentNotifications(aFeed)
{
// return; // FIXME turn this back on later
this._logger.info("JMC: Handling comment notification...");
aFeed.QueryInterface(Components.interfaces.flockIFeed);
var feedURL = aFeed.getURL().spec;
feedURL.match(/\.gne\?.+id=(.+?)&/);
var aAccountID = RegExp.$1;
var account = this.faves_coop.get("urn:flock:flickr:account:" + aAccountID);
// For each unread item,
// Create a notification
// If there's already a notification for that photo,
// -- if the notification is unread, add to it
// -- otherwise, replace it and mark it unread again
var commentEnums = aFeed.getUnreadItems();
while (commentEnums.hasMoreElements()) {
var comment = commentEnums.getNext();
comment.QueryInterface(Components.interfaces.flockIFeedItem);
// If the comment is by me, don't notify
if (comment.getAuthor().indexOf(account.name) > -1) {
comment.setRead(true);
continue;
}
var commenturl = comment.getLink();
commenturl = commenturl.spec;
// http://www.flickr.com/photos/join_the_flock/49599935/#comment72157594348910818
commenturl.match(/\/photos\/.+\/(\d+)\/\#/);
var photoid = RegExp.$1;
var titlestring = comment.getTitle();
titlestring.match(/Comment about (.+)/);
var photoTitle = RegExp.$1;
var notificationStream = "urn:flock:flickr:account:"+aAccountID+":notifications";
var notificationurn = "urn:flock:flickr:account:"+aAccountID+":notification:photo:"+photoid;
var notif = this.faves_coop.get(notificationurn);
if (notif) {
if (!notif.unseen) {
notif.URL = commenturl;
notif.unseen = true;
}
notif.title = "'" + photoTitle + "' - New comment on Flickr";
notif.description = "There is a new comment about '" + photoTitle + "'";
} else {
var nProps = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
nProps.setPropertyAsAString("favicon", FLICKR_FAVICON);
nProps.setPropertyAsAString("type", "PhotoComment");
nProps.setPropertyAsAString("name", "PhotoComment");
nProps.setPropertyAsAString("description", "There is a new comment about '" + photoTitle + "'");
nProps.setPropertyAsAString("title", "'" + photoTitle + "' - New comment on Flickr");
nProps.setPropertyAsAString("URL", commenturl);
nProps.setPropertyAsAString("unseen", "true");
this.acUtils.raiseNotification( notificationStream,
notificationurn,
nProps );
}
comment.setRead(true);
}
}
flickrService.prototype.serviceName = "Flickr";
flickrService.prototype.shortName = "flickr";
flickrService.prototype.handleInfoResult = function(aXML) {
var photo = aXML.getElementsByTagName("photo")[0];
var owner = aXML.getElementsByTagName("owner")[0];
var visibility = aXML.getElementsByTagName("visibility")[0];
var title = aXML.getElementsByTagName("title")[0].firstChild.nodeValue;
var dates = aXML.getElementsByTagName("dates")[0];
var id = photo.getAttribute("id");
var server = photo.getAttribute("server");
var secret = photo.getAttribute("secret");
var lastUpdate = dates.lastupdate;
var uploadDate = dates.posted;
var square_url = flock_flickrBuildPhotoUrl(server,id,secret,'square');
var small_url = flock_flickrBuildPhotoUrl(server,id,secret,'small');
var med_url = flock_flickrBuildPhotoUrl(server,id,secret,'medium');
var page_url = flock_flickrBuildPageUrl(owner.getAttribute('nsid'),id);
var icon_server = photo.getAttribute("iconserver");
var newPhoto = new flickrPhoto();
newPhoto.webPageUrl = page_url;
newPhoto.thumbnail = square_url;
newPhoto.midSizePhoto = small_url;
newPhoto.largeSizePhoto = med_url;
newPhoto.username = owner.getAttribute('username');
newPhoto.title = title;
newPhoto.id = id;
newPhoto.lastUpdate = lastUpdate;
newPhoto.uploadDate = parseInt(uploadDate)*1000;
if (icon_server == '1') {
newPhoto.icon = 'http://www.flickr.com/images/buddyicon.jpg';
}
else {
newPhoto.icon = 'http://static.flickr.com/' + icon_server + '/buddyicons/' + owner +'.jpg';
}
var ispublic = visibility.getAttribute("ispublic");
if (ispublic =="1") ispublic = "true";
else ispublic = "false";
newPhoto.is_public = ispublic;
newPhoto.is_video = false;
return newPhoto;
}
flickrService.prototype.handlePhotosResult =
function (aXML, aUserid)
{
var rval = [];
var photoList = aXML.getElementsByTagName("photo");
for (var i = 0; i < photoList.length; i++) {
var photo = photoList[i];
var id = photo.getAttribute("id");
var server = photo.getAttribute("server");
var secret = photo.getAttribute("secret");
var title = photo.getAttribute("title");
var owner = photo.getAttribute("owner");
if (!owner) owner = aUserid;
var owner_name = photo.getAttribute("ownername");
var date_upload = photo.getAttribute("dateupload");
var date_added = photo.getAttribute("dateadded");
var icon_server = photo.getAttribute("iconserver");
var square_url = flock_flickrBuildPhotoUrl(server,id,secret,'square');
var small_url = flock_flickrBuildPhotoUrl(server,id,secret,'small');
var med_url = flock_flickrBuildPhotoUrl(server,id,secret,'medium');
var page_url = flock_flickrBuildPageUrl(owner,id);
var newPhoto = new flickrPhoto();
newPhoto.webPageUrl = page_url;
newPhoto.thumbnail = square_url;
newPhoto.midSizePhoto = small_url;
newPhoto.largeSizePhoto = med_url;
newPhoto.username = owner_name;
newPhoto.userid = owner;
newPhoto.title = title;
newPhoto.id = id;
if (icon_server == '1') {
newPhoto.icon = 'http://www.flickr.com/images/buddyicon.jpg';
}
else {
newPhoto.icon = 'http://static.flickr.com/' + icon_server + '/buddyicons/' + owner +'.jpg';
}
newPhoto.uploadDate = parseInt((date_added) ? date_added : date_upload)*1000;
// if the photo result set doesn't return back the ispublic
// attribute, we assume that the server is returning only
// public photos back in the response
if (photo.hasAttribute("ispublic")) {
var ispublic = photo.getAttribute("ispublic");
if (ispublic =="1") ispublic = "true";
else ispublic = "false";
} else {
ispublic = "true";
}
newPhoto.is_public = ispublic;
newPhoto.is_video = false;
rval.push(newPhoto);
}
return rval;
}
flickrService.prototype.getPhotoFromRDFNode =
function (aRDFId)
{
var newPhoto = new flickrPhoto();
var coopPhoto = this.faves_coop.get(aRDFId);
newPhoto.webPageUrl = coopPhoto.URL;
newPhoto.thumbnail = coopPhoto.thumbnail;
newPhoto.midSizePhoto = coopPhoto.midSizePhoto;
newPhoto.largeSizePhoto = coopPhoto.largeSizePhoto;
newPhoto.username = coopPhoto.username;
newPhoto.userid = coopPhoto.userid;
newPhoto.title = coopPhoto.name;
newPhoto.id = coopPhoto.photoid;
newPhoto.icon = coopPhoto.favicon;
newPhoto.uploadDate = coopPhoto.datevalue;
newPhoto.is_public = coopPhoto.is_public;
newPhoto.is_video = coopPhoto.is_video;
return newPhoto;
}
flickrService.prototype.handleContactsResult =
function (aXML)
{
var rval = [];
var contactList = aXML.getElementsByTagName("contact");
for (var i = 0; i < contactList.length; i++) {
var contact = contactList[i];
var nsid = contact.getAttribute("nsid");
var username = contact.getAttribute("username");
var fullname = contact.getAttribute("fullname");
var family = contact.getAttribute("family");
var friend = contact.getAttribute("friend");
var iconserver = contact.getAttribute("iconserver");
if (true || family == "1" || friend == "1") {
this._logger.info(".handleContactsResult(): username="+username+" family="+family+" friend="+friend);
// implement flockIPhotoPerson
//var newContact = {};
var newContact = Components.classes[FLOCK_PHOTOPERSON_CONTRACTID]
.createInstance(flockIPhotoPerson);
newContact.id = nsid;
newContact.username = username;
newContact.fullname = username;
newContact.service = this;
newContact.avatarUrl = 'http://static.flickr.com/'+iconserver+'/buddyicons/'+nsid+'.jpg'
rval.push(newContact);
}
}
return rval;
}
flickrService.prototype.handleAlbumsResult =
function (aXML)
{
var rval = [];
var photosetList = aXML.getElementsByTagName("photoset");
var titleList = aXML.getElementsByTagName("title");
for (var i = 0; i < photosetList.length; i++) {
var id = photosetList[i].getAttribute("id");
var title = titleList[i].firstChild.nodeValue;
var newAlbum = Components.classes[FLOCK_PHOTO_ALBUM_CONTRACTID]
.createInstance(flockIPhotoAlbum);
newAlbum.id = id;
newAlbum.title = title;
rval.push(newAlbum);
}
return rval;
}
flickrService.prototype.getContacts =
function flickrService_getContacts(aListener)
{
this._logger.info(".getContacts(...)");
var inst = this;
var myListener = {
onResult: function (aXML) {
var rval = inst.handleContactsResult(aXML);
var enum_ = {
hasMoreElements: function() {
return (rval.length > 0);
},
getNext: function() {
return rval.shift();
}
}
aListener.onGetContactsResult(enum_);
},
onError: function (aError) {
aListener.onError(aError);
}
}
var params = {};
var dict = params2Dictionary(params);
this.authenticatedCall(myListener, "flickr.contacts.getList", dict);
}
flickrService.prototype.getFriendsContacts =
function flickrService_getFriendsContacts(aListener, aUserID)
{
this._logger.info(".getFriendsContacts(...)");
var inst = this;
var myListener = {
onResult: function (aXML) {
var rval = inst.handleContactsResult(aXML);
var enum_ = {
hasMoreElements: function() {
return (rval.length>0);
},
getNext: function() {
return rval.shift();
}
}
aListener.onGetContactsResult(enum_);
},
onError: function (aError) {
aListener.onError(aError);
}
}
var params = {};
params.user_id = aUserID;
var dict = params2Dictionary(params);
this.call(myListener, "flickr.contacts.getPublicList", dict);
}
flickrService.prototype.getPhoto =
function (aListener, aID)
{
var inst = this;
var myListener = {
onResult: function (aXML) {
var photo = inst.handleInfoResult(aXML);
aListener.onGetPhotoResult(photo);
},
onError: function (aError) {
aListener.onError(aError);
}
}
var params = {};
params.photo_id = aID;
var dict = params2Dictionary(params);
if (this.getAuthUser()) {
this.authenticatedCall(myListener, "flickr.photos.getInfo", dict);
} else {
this.call(myListener, "flickr.photos.getInfo", dict);
}
}
flickrService.prototype.fakeAlbums = {};
flickrService.prototype.realishAlbums = {};
flickrService.prototype.createAlbum =
function (aListener, aTitle)
{
// trim white space from front and end of string
aTitle = aTitle.replace(/^\s+|\s+$/g, "");
if (aTitle) {
var newAlbum = Components.classes[FLOCK_PHOTO_ALBUM_CONTRACTID]
.createInstance(flockIPhotoAlbum);
newAlbum.title = aTitle;
var date = new Date(); //hopefully this won't collide with an actual id!
newAlbum.id = date.getTime();
this.fakeAlbums[newAlbum.id] = newAlbum;
aListener.onCreateAlbum(newAlbum);
} else {
var error = Components.classes[FLOCK_ERROR_CONTRACTID].createInstance(flockIError);
error.errorCode = error.PHOTOSERVICE_EMPTY_ALBUMNAME;
aListener.onError(error);
}
}
flickrService.prototype.reallyCreateAlbum =
function (aListener, aTitle, aID)
{
var inst = this;
var myListener = {
onResult: function (aXML) {
var newAlbum = Components.classes[FLOCK_PHOTO_ALBUM_CONTRACTID]
.createInstance(flockIPhotoAlbum);
var photoset = aXML.getElementsByTagName("photoset")[0];
newAlbum.title = aTitle;
newAlbum.id = photoset.getAttribute("id");;
aListener.onCreateAlbumResult(newAlbum);
},
onError: function (aXML) {
aListener.onError(aXML);
}
}
var params = {};
params.title = aTitle;
params.primary_photo_id = aID;
var dict = params2Dictionary(params);
this.authenticatedCall(myListener, "flickr.photosets.create", dict);
}
flickrService.prototype.getAlbums =
function flickrService_getAlbums(aListener, aUsername)
{
var inst = this;
var myListener = {
onResult: function (aXML) {
try {
var rval = inst.handleAlbumsResult(aXML);
var enum_ = {
hasMoreElements: function() {
return (rval.length>0);
},
getNext: function() {
return rval.shift();
}
}
aListener.onGetAlbumsResult(enum_);
} catch(e) {
aListener.onError(null);
}
},
onError: function (aXML) {
aListener.onError(aXML);
}
}
var params = {};
if (aUsername) {
params.user_id = aUsername;
}
var dict = params2Dictionary(params);
if (this.getAuthUser()) {
this.authenticatedCall(myListener, "flickr.photosets.getList", dict);
} else {
this.call(myListener, "flickr.photosets.getList", dict);
}
}
flickrService.prototype.getAccountStatus =
function flickrService_getAccountStatus(aListener)
{
var inst = this;
var myListener = {
onResult:function (aXML) {
try {
inst._logger.info('we got a result for account status...');
var photoAccount = Components.classes[FLOCK_PHOTO_ACCOUNT_CONTRACTID].createInstance(flockIPhotoAccount);
var username = aXML.getElementsByTagName('username')[0].firstChild.nodeValue;
var bandwidth = aXML.getElementsByTagName('bandwidth')[0];
var maxFileSize = aXML.getElementsByTagName('filesize')[0];
var isPro = aXML.getElementsByTagName('user')[0].getAttribute('ispro');
photoAccount.username = username;
photoAccount.maxSpace = bandwidth.getAttribute('max');
photoAccount.usedSpace = bandwidth.getAttribute('used');
photoAccount.maxFileSize = maxFileSize;
photoAccount.usageUnits = "bytes";
photoAccount.isPremium = (isPro == "1" ? true: false);
aListener.onGetAccountStatus(photoAccount);
} catch (ex) {
inst._logger.info('getaccountstatus error >>>>>>>>>>>>>>>>>>>>' + ex);
}
},
onError: function (aError) {
aListener.onError(aError);
}
}
var params = {};
var dict = params2Dictionary(params);
this.authenticatedCall(myListener, "flickr.people.getUploadStatus", dict);
}
flickrService.prototype.getContactsPhotos =
function flickrService_getContactsPhotos(aListener)
{
// return; // XXX TODO FIXME (JMC): Save me from contacts' photos hanging my browser!
var inst = this;
var myListener = {
onResult: function (aXML) {
var rval = inst.handlePhotosResult(aXML);
var enum_ = {
hasMoreElements: function() {
return (rval.length>0);
},
getNext: function() {
return rval.shift();
}
}
aListener.onSearchResult(enum_);
},
onError: function (aXML) {
aListener.onError(null);
}
}
var params = {};
params.single_photo = "1";
params.include_self = "1";
params.extras = "owner_name,license,date_upload,icon_server";
var dict = params2Dictionary(params);
this.authenticatedCall(myListener, "flickr.photos.getContactsPhotos", dict);
}
flickrService.prototype.getMostRecentPhotoForList =
function flickrService_getMostRecentPhotoForList(aListener, aEnumerator)
{
var mg = new MultiGetter();
mg.init(this, aListener, aEnumerator);
}
flickrService.prototype.findByUsername =
function flickrService_findByUsername(aListener, aUsername)
{
var inst = this;
var userListener = function(aListener) {
this.mListener = aListener;
}
userListener.prototype.onGetInfo = function (aPerson) {
this.mListener.onFindByUsernameResult(aPerson);
}
userListener.prototype.onError = function (aError) {
inst._logger.info(aError);
this.mListener.onError(aError);
}
var myListener = {
onResult: function (aXML) {
var user = aXML.getElementsByTagName("user")[0];
var id = user.getAttribute("id");
inst.people_getInfo(new userListener(aListener), id);
},
onError: function (aXML) {
aListener.onError(aXML);
}
}
var params = {};
params.username = aUsername;
var dict = params2Dictionary(params);
this.call(myListener, "flickr.people.findByUsername", dict);
}
flickrService.prototype.lookupUser =
function (aListener, aURL)
{
var inst = this;
var myListener = {
onResult: function (aXML) {
var newUserObj = Components.classes[FLOCK_PHOTOPERSON_CONTRACTID]
.createInstance(flockIPhotoPerson);
var user = aXML.getElementsByTagName("user")[0];
newUserObj.service = inst;
newUserObj.id = user.getAttribute("id");
newUserObj.username = user.getElementsByTagName("username")[0].childNodes[0].nodeValue;
newUserObj.fullname = newUserObj.username;
aListener.onLookupUser(newUserObj);
},
onError: function (aXML) {
aListener.onError(aXML);
}
}
var params = {};
params.url = aURL;
var dict = params2Dictionary(params);
this.call(myListener, "flickr.urls.lookupUser", dict);
}
flickrService.prototype.getValidPerson =
function (aListener, aURL)
{
this.lookupUser( {
onLookupUser: aListener.onGetValidPerson,
onError: aListener.onError
}, aURL );
}
flickrService.prototype.people_getInfo =
function (aListener, aUserId)
{
var inst = this;
var myListener = {
onResult: function (aXML) {
var newUserObj = Components.classes[FLOCK_PHOTOPERSON_CONTRACTID].createInstance(flockIPhotoPerson);
var person = aXML.getElementsByTagName("person")[0];
var iconserver = person.getAttribute("iconserver");
var count = person.getElementsByTagName("photos")[0].getElementsByTagName("count")[0].firstChild.nodeValue;
newUserObj.service = inst;
newUserObj.id = person.getAttribute("id");
newUserObj.username = person.getElementsByTagName('username')[0].firstChild.nodeValue + '';
newUserObj.fullname = newUserObj.username;
newUserObj.avatarUrl = 'http://static.flickr.com/'+iconserver+'/buddyicons/'+newUserObj.id+'.jpg'
newUserObj.photoCount = parseInt(count);
aListener.onGetInfo(newUserObj);
},
onError: function (aXML) {
aListener.onError(aXML);
}
}
var params = {};
params.user_id = aUserId;
var dict = params2Dictionary(params);
this.call(myListener, "flickr.people.getInfo", dict);
}
flickrService.prototype.queryChannel =
function flickrService_queryChannel(aListener, aQueryString, aCount, aPage)
{
var aQuery = new queryHelper(aQueryString);
// return; // XXX TODO FIXME: This is killing performance!
var inst=this;
var myListener = {
onResult: function (aXML) {
var rval = inst.handlePhotosResult(aXML);
var enum_ = {
hasMoreElements: function() {
return (rval.length>0);
},
getNext: function() {
return rval.shift();
}
}
aListener.onSearchResult(enum_);
},
onError: function (aError) {
aListener.onError(aError);
}
}
var params = {
per_page: aCount,
page: aPage,
extras: "owner_name,icon_server,date_upload,license"
};
if (aQuery.getKey('special') == 'recent') {
if (aQuery.hasKey('search')) {
params.text = aQuery.getKey('search');
var dict = params2Dictionary(params);
this.call(myListener, "flickr.photos.search", dict);
} else {
var dict = params2Dictionary(params);
this.call(myListener, "flickr.photos.getRecent", dict)
}
}
if (aQuery.getKey("special") == 'interestingness') {
if (aQuery.hasKey('search')) {
params.text = aQuery.getKey('search');
params.sort = 'interestingness-desc';
var dict = params2Dictionary(params);
this.call(myListener, "flickr.photos.search", dict);
} else {
var dict = params2Dictionary(params);
this.call(myListener, "flickr.interestingness.getList", dict)
}
}
if (aQuery.hasKey('search')) {
aText = aQuery.getKey('search');
if (aText && aText.length) {
params.text = aText;
var dict = params2Dictionary(params);
this.call(myListener, "flickr.photos.search", dict);
}
}
}
flickrService.prototype.poolSearch =
function flickrService_poolSearch(aListener, aQueryString, aCount, aPage)
{
var aQuery = new queryHelper(aQueryString);
var inst = this;
var myListener = {
onResult: function (aXML) {
var rval = inst.handlePhotosResult(aXML);
var enum_ = {
hasMoreElements: function() {
return (rval.length>0);
},
getNext: function() {
return rval.shift();
}
}
aListener.onSearchResult(enum_);
},
onError: function (aError) {
aListener.onError(aError);
}
}
/*
var aText;
if (aQuery.split('?').length > 1) {
aText = aQuery.split('?')[1];
aQuery = aQuery.split('?')[0];
}
aQuery = aQuery.split(':')[1]
*/
var params = {
group_id: aQuery.pool,
per_page: aCount,
page: aPage,
extras: "owner_name,icon_server,date_upload,license"
};
if (aQuery.search) {
params.tags = aQuery.search;
var dict = params2Dictionary(params);
this.call(myListener, "flickr.groups.pools.getPhotos", dict);
} else {
var dict = params2Dictionary(params);
this.call(myListener, "flickr.groups.pools.getPhotos", dict)
}
}
flickrService.prototype.search =
function flickrService_search(aListener, aQueryString, aCount, aPage)
{
// return; // FIXME - turn this back on later
var aQuery = new queryHelper(aQueryString);
if (aQuery.pool) {
this.poolSearch(aListener, aQueryString, aCount, aPage);
return;
}
if (!aQuery.user) {
this.queryChannel(aListener, aQueryString, aCount, aPage);
return;
}
var aUserid = aQuery.user;
var inst = this;
var myListener = {
onResult: function (aXML) {
var rval = inst.handlePhotosResult(aXML, aUserid);
var enum_ = {
hasMoreElements: function() {
return (rval.length>0);
},
getNext: function() {
return rval.shift();
}
}
aListener.onSearchResult(enum_);
},
onError: function (aError) {
aListener.onError(aError);
}
}
// Flickr return the photo in the reverse side when calling flickr.photosets.getPhotos!
// So we need to enumerate backward :-/
var myPhotosetListener = {
onResult: function (aXML) {
var rval = inst.handlePhotosResult(aXML, aUserid);
var enum_ = {
hasMoreElements: function() {
return (rval.length>0);
},
getNext: function() {
return rval.pop();
}
}
aListener.onSearchResult(enum_);
},
onError: function (aError) {
aListener.onError(aError);
}
}
var params = {};
if (aUserid && aUserid.length) params.user_id = aUserid;
params.per_page = aCount;
params.page = aPage;
if (aQuery.search) params.text = aQuery.search;
params.tag_mode = "all";
params.extras = "owner_name,license,date_upload,icon_server";
if (aQuery.album) {
params.photoset_id = aQuery.album;
}
var dict = params2Dictionary(params);
if (params.photoset_id) {
if (aPage > 1) return; // this is because the flickr call doesn't support pagination [bug 4770]
dict = params2Dictionary(params);
if (this.getAuthUser())
this.authenticatedCall(myPhotosetListener, "flickr.photosets.getPhotos", dict);
else
this.call(myPhotosetListener, "flickr.photosets.getPhotos", dict);
} else if (params.user_id || params.text) {
if (this.isLoggedIn) this.authenticatedCall(myListener, "flickr.photos.search", dict);
else this.call(myListener, "flickr.photos.search", dict);
}
}
flickrService.prototype.supportsSearch =
function flickrService_supportsSearch( aQueryString ) {
var aQuery = new queryHelper(aQueryString);
if (aQuery.special) {
var channel = channels["special:" + aQuery.special];
if (channel) {
return channel.supportsSearch;
}
}
if (aQuery.album) return false;
if (aQuery.user) return true;
if (aQuery.search) return false;
return false;
}
var channels = {
"special:recent": {
title: "Recent Public Photos",
supportsSearch: false
},
"special:interestingness": {
title: "Interestingness",
supportsSearch: true
}
}
flickrService.prototype.getChannel =
function flickrService_getChannel(aChannelId)
{
if (!(aChannelId in channels)) return null;
var nc = Components.classes["@flock.com/media-channel;1"]
.createInstance(Components.interfaces.flockIMediaChannel);
nc.id = aChannelId;
nc.title = channels[aChannelId].title
nc.supportsSearch = channels[aChannelId].supportsSearch;
return nc;
}
flickrService.prototype.__defineGetter__("channels", function () {
var ar = [];
for (var id in channels) {
var nc = Components.classes["@flock.com/media-channel;1"]
.createInstance(Components.interfaces.flockIMediaChannel);
nc.id = id;
nc.title = channels[id].title
nc.supportsSearch = channels[id].supportsSearch;
ar.push(nc);
}
var rval = {
getNext: function() {
var rval = ar.shift();
return rval;
},
hasMoreElements: function() {
return (ar.length>0);
}
}
return rval;
})
flickrService.prototype.mSupportsTitle = true;
flickrService.prototype.mSupportsTags = true;
flickrService.prototype.mSupportsContacts = true;
flickrService.prototype.mSupportsPrivacy = true;
flickrService.prototype.iconUrl = "chrome://browser/skin/flock/photo/flickrIcon.png";
flickrService.prototype.supportsFeature =
function flickrService_supportsFeature(aFeature)
{
var supports = {};
supports.tags = true;
supports.title = true;
supports.fileName = false;
supports.contacts = true;
supports.privacy = true;
supports.albumCreation = true;
return (supports[aFeature] == true);
}
flickrService.prototype.init =
function flickrService_init()
{
// Prevent re-entry
if (this.mIsInitialized) return;
this.mIsInitialized = true;
this._logger.info(".init()");
var evtID = this._profiler.profileEventStart("flickr-init");
// Determine whether this service has been disabled, and unregister if so.
this.prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
if ( this.prefService.getPrefType(SERVICE_ENABLED_PREF) &&
!this.prefService.getBoolPref(SERVICE_ENABLED_PREF) )
{
this._logger.info("Pref "+SERVICE_ENABLED_PREF+" set to FALSE... not initializing.");
var catMgr = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
catMgr.deleteCategoryEntry("wsm-startup", CATEGORY_COMPONENT_NAME, true);
catMgr.deleteCategoryEntry("flockIPhotoAPI", CATEGORY_ENTRY_NAME, true);
catMgr.deleteCategoryEntry("flockWebService", CATEGORY_ENTRY_NAME, true);
return;
}
this.api = new FlickrAPI();
this.api.svc = this;
var inst = this;
this.faves_coop = Components.classes["@flock.com/singleton;1"]
.getService(Components.interfaces.flockISingleton)
.getSingleton("chrome://browser/content/flock/common/load-faves-coop.js")
.wrappedJSObject;
this.obs.addObserver(this, "new-feed-items", false);
this.urn = "urn:flickr:service";
this.svcCoopObj = new this.faves_coop.Service(
this.urn,
{
name: "flickr",
desc: "The Flickr Service",
contactLabel: 'Contacts'
}
);
this.svcCoopObj.serviceId = FLICKR_CONTRACTID;
// Load Web Detective file
this.webDetective = this.acUtils.useWebDetective("flickr.xml");
for (var s in gStrings) {
gStrings[s] = this.webDetective.getString("flickr", s, gStrings[s]);
}
this.svcCoopObj.domains = gStrings["domains"];
this.svcCoopObj.loginURL = gStrings["userlogin"];
// Update auth states
try {
if (this.webDetective.detectCookies("flickr", "loggedout", null)) {
this.acUtils.markAllAccountsAsLoggedOut(FLICKR_CONTRACTID);
this.api.logout();
this.state = flockIPhotoAPI.LOGGED_OUT;
}
} catch (ex) {
this._logger.error("ERROR updating auth states for Flickr: "+ex);
}
var timerFunc = {
inProgress: false,
count: 0,
observe: function(subject, topic, state) {
//if (topic == 'nsPref:changed' && state == FLICKR_TOKEN_PREF_ID) {
// var oldToken = flock_getCharPref(FLICKR_TOKEN_PREF_ID);
// if (oldToken && oldToken.length && !inst.api.isLoggedIn()) {
// this.inProgress = true;
// inst.api.checkToken(this, oldToken);
// }
//}
},
notify: function(aTimer) {
if (this.inProgress) return;
if (inst.api.isLoggedIn()) {
inst.api.processPendingUploadTickets();
inst.api.processPendingAlbumAdditions();
}
},
onResult: function(aXML) {
this.inProgress = false;
},
onAuth: function(aXML) {
this.inProgress = false;
inst.state = flockIPhotoAPI.LOGGED_IN;
},
onError: function(aError) {
inst.logout();
this.inProgress = false;
}
}
//timerFunc.observe(null, 'nsPref:changed', FLICKR_TOKEN_PREF_ID);
timerFunc.notify();
//var prefs = Components.classes['@mozilla.org/preferences-service;1']
// .getService(Components.interfaces.nsIPrefBranch2);
//prefs.addObserver(FLICKR_TOKEN_PREF_ID, timerFunc, false);
timer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer);
timer.initWithCallback(timerFunc, 5 * 1 * 1000, 1); //re-check token
this._profiler.profileEventEnd(evtID, "");
}
flickrService.prototype.__defineGetter__('supportsTitle', function () { return this.mSupportsTitle; })
flickrService.prototype.__defineGetter__('supportsTags', function () { return this.mSupportsTags; })
flickrService.prototype.__defineGetter__('supportsContacts', function () { return this.mSupportsContacts; })
flickrService.prototype.__defineGetter__('supportsPrivacy', function () { return this.mSupportsPrivacy; })
flickrService.prototype.getAuthState =
function flickrService_getAuthState()
{
return this.state;
}
flickrService.prototype.__defineGetter__('authState', function () { return this.state; })
flickrService.prototype.logout =
function flickrService_logout()
{
this.api.logout();
this.state = flockIPhotoAPI.LOGGED_OUT;
this.acUtils.removeCookies(this.webDetective.getSessionCookies("flickr"));
}
flickrService.prototype.login =
function flickrService_login(aAccountURN, aListener)
{
var inst = this;
var myListener = {
onAuth: function () {
inst.state = flockIPhotoAPI.LOGGED_IN;
inst.acUtils.ensureOnlyAuthenticatedAccount(aAccountURN);
if (aListener) aListener.onAuth();
},
onError: function (aError) {
inst.state = flockIPhotoAPI.LOGIN_ERROR;
if (aListener) aListener.onError(aError);
}
}
this.api.logout();
this.acUtils.markAllAccountsAsLoggedOut(FLICKR_CONTRACTID);
inst.state = flockIPhotoAPI.LOGGING_IN;
this.api.login(aAccountURN, myListener);
}
flickrService.prototype.__defineGetter__('isLoggedIn', function () { return this.api.isLoggedIn(); })
flickrService.prototype.getAuthUser = function () {
return this.api.getAuthUser();
}
flickrService.prototype.getAuthPerson = function () {
try {
var user = this.api.getAuthUser();
var person = {};
person.id = user.id;
person.fullname = user.fullname;
person.username = user.username;
person.service = this;
return person;
}
catch(e) {
return null;
}
}
flickrService.prototype.__defineGetter__('isUploading', function () { return this.running; })
flickrService.prototype.dictionary2Params =
function flickrService_dictionary2Params(aDictionary)
{
var params = {};
var obj = {};
var count = {};
var keys = aDictionary.getKeys(count, obj);
for (var i = 0; i < keys.length;++i) {
var supports = aDictionary.getValue(keys[i]);
var supportsString = supports.QueryInterface(Components.interfaces.nsISupportsString);
var val = supportsString.toString();
params[keys[i]] = val;
}
return params;
}
flickrService.prototype.call =
function flickrService_call(aListener, aMethod, aDictionary)
{
var params = this.dictionary2Params(aDictionary);
this.api.call(aListener, aMethod, params);
}
flickrService.prototype.authenticatedCall =
function flickrService_authenticatedCall(aListener, aMethod, aDictionary)
{
if (!this.isLoggedIn) throw "not logged in";
var params = this.dictionary2Params(aDictionary);
this.api.authenticatedCall(aListener, aMethod, params);
}
flickrService.prototype.upload2 =
function flickrService_upload2(aListener, aUpload, aFile)
{
var params = {};
params.title = aUpload.title;
params.description = aUpload.description;
params.is_family = aUpload.is_family;
params.is_friend = aUpload.is_friend;
params.is_public = aUpload.is_public;
params.async = "1";
params.tags = aUpload.tags;
this.api.upload(aListener, aFile, params, aUpload);
}
flickrService.prototype.cancelUpload =
function flickrService_cancelUpload()
{
try { this.api.uploader.req.abort(); }
catch(e){};
}
// *** XXX TODO CDC: Generalize this!
flickrService.prototype.openSendMessageTabForFill =
function flickrService_openSendMessageTabForFill(aFriendID, aSubject, aBody)
{
// Get top level window
var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1']
.getService(Components.interfaces.nsIWindowMediator);
var topWin = windowManager.getMostRecentWindow("navigator:browser");
var browser = topWin.getBrowser();
var newTab = browser.loadOneTab(gStrings["privatemessage"], null, null, null, false, false);
var inst = this;
var observer = {
observe: function(subject, topic, state) {
var thisWindow = newTab.linkedBrowser.docShell
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
if (thisWindow.document == subject) {
var form = inst.acUtils.getElementByAttribute(thisWindow.document.documentElement, "action", "messages_write.gne");
form.QueryInterface(Components.interfaces.nsIDOMHTMLFormElement);
form.elements.namedItem('to_nsid').value = aFriendID;
form.elements.namedItem('subject').value = aSubject;
form.elements.namedItem('message').value = aBody;
inst.obs.removeObserver(this, 'FlockDocumentReady');
}
}
}
this.obs.addObserver(observer, 'FlockDocumentReady', false);
}
flickrService.prototype.doAction =
function flickrService_doAction(aActionName, aURN, aSubject)
{
var identityTarget = this.faves_coop.get(aURN);
switch (aActionName)
{
case "uploadPhotos":
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var win = wm.getMostRecentWindow('navigator:browser');
if (win) {
win.flock_photo.util.launchUploader();
}
break;
default:
break;
}
}
flickrService.prototype.updateActions =
function flickrService_updateActions(aURN)
{
var coopObj = this.faves_coop.get(aURN);
if (coopObj.isInstanceOf(this.faves_coop.Account)) {
coopObj.enabledAction.removeAll();
var serviceActions = this.svcCoopObj.children.enumerate();
while (serviceActions.hasMoreElements()) {
var action = serviceActions.getNext();
if (action.flavour == "accountaction" ||
action.flavour == "view")
{
coopObj.enabledAction.add(action);
}
}
}
}
// JMC - XXX TODO, factor common code out of these two methods
flickrService.prototype.addFoafPerson =
function flickrService_addFoafPerson(aPhotoPerson, aFriendOfURN)
{
this._logger.info(".addFoafPerson('"+aFriendOfURN+"')");
}
flickrService.prototype.addPhotostream =
function flickrService_addPhotostream(aPhotoPerson, aCoopAccount)
{
this._logger.info(".addPhotostream('"+aPhotoPerson.username+"')");
var aQuery = new queryHelper();
aQuery.user = aPhotoPerson.id;
aQuery.username = aPhotoPerson.fullname;
var mediaqueryURN = "urn:media:favorites:flickr:"+aQuery.stringVal;
var mediaquery = this.faves_coop.get(mediaqueryURN);
if (!mediaquery) {
mediaquery = new this.faves_coop.MediaQuery(
mediaqueryURN,
{
serviceId: PHOTOAPIMGR_CONTRACTID,
service: this.shortName,
favicon: FLICKR_FAVICON
}
);
}
mediaquery.query = aQuery.stringVal;
mediaquery.name = aPhotoPerson.fullname;
mediaquery.isPollable = true;
mediaquery.isTransient = aCoopAccount.isTransient;
var mediaFavesURN = "urn:media:favorites";
var mediaFaves = this.faves_coop.get(mediaFavesURN);
if (!mediaFaves) {
mediaFaves = new this.faves_coop.Folder(mediaFavesURN);
this.faves_coop.favorites_root.children.add(mediaFaves);
}
mediaFaves.children.addOnce(mediaquery);
}
flickrService.prototype.addCoopPerson =
function flickrService_addCoopPerson(aPhotoPerson, refreshItem)
{
}
// BEGIN flockIPollingService
flickrService.prototype.refresh =
function flickrService_refresh(aURN, aListener)
{
this._logger.info("{flockIPollingService}.refresh('"+aURN+"', ...)");
var refreshItem = this.faves_coop.get(aURN);
var inst = this;
if (refreshItem instanceof this.faves_coop.Account) {
if (!refreshItem.isAuthenticated) {
// aListener.onError();
return;
}
this.getContacts({
onGetContactsResult: function (enumPeople) {
// Found some people
function myWorker(shouldYield) {
var count = 0;
while (enumPeople.hasMoreElements()) {
var person = enumPeople.getNext();
count++;
//inst.addCoopPerson(person, refreshItem);
inst.addPhotostream(person, refreshItem);
if (shouldYield()) {
yield;
}
}
aListener.onResult();
}
getCompTK().schedule(gTimers, 0.3, 30, myWorker);
},
onError: function (aError) {
//aListener.onError(aError);
}
});
// Essentially the importStreams actions
}
aListener.onResult();
}
// END flockIPollingService
flickrService.prototype.migrateAccount =
function flickrService_migrateAccount( aId, aUsername ) {
this.init();
var token = '';
/*
try {
token = flock_getCharPref('flock.photo.flickr.token');
} catch (e) { }
*/
this.addAccountById( aId, false, null, aUsername, token);
}
// BEGIN flockIWebService interface
flickrService.prototype.addAccountById =
function flickrService_addAccountById(aAccountID, aIsTransient, aListener, aUsername, aToken)
{
this._logger.info("{flockIWebService}.addAccountById('"+aAccountID+"', "+aIsTransient+")");
if (!aUsername) {
// Get the password associated with this account
var pw = this.acUtils.getPassword(this.urn+':'+aAccountID);
// FIX ME - name shouldn't be email address (pw.user) - ja
var name = (pw) ? pw.user : aAccountID;
var token = '';
var pollable = false;
var auth = false;
} else {
var name = aUsername;
var token = aToken;
var pollable = true;
var auth = true;
}
// Account
var accountURN = "urn:flock:flickr:account:"+aAccountID;
var account = new this.faves_coop.Account(accountURN, {
name: name,
accountId: aAccountID,
serviceId: FLICKR_CONTRACTID,
service: this.svcCoopObj,
favicon: FLICKR_FAVICON,
URL: gStrings["userprofile"].replace("%accountid%", aAccountID),
isTransient: aIsTransient,
isPollable: pollable,
authToken: token,
isAuthenticated: auth
});
this.faves_coop.accounts_root.children.add(account);
/*********************
/* PHAN: taking these streams out for now. Matt will need them
later for people
// Photostream
var photostreamURN = "urn:flock:stream:photo:flickr:"+aAccountID;
var photostream = new this.faves_coop.Stream(photostreamURN, {
name: name + "'s PhotoStream",
favicon: FLICKR_FAVICON,
isPollable: true,
apiType: "flickr",
serviceId: PHOTOAPIMGR_CONTRACTID,
userid: aAccountID,
flockType: "photostream",
URL: gStrings["userphotos"].replace("%accountid%", aAccountID)
});
account.children.addOnce(photostream);
var notificationstream = new this.faves_coop.Stream(accountURN+":notifications", {
isPollable: false,
isIndexable: false,
notify: true,
serviceId: FLICKR_CONTRACTID
});
account.children.addOnce(notificationstream);
// Flickr comments activity
var commentstream = new this.faves_coop.Feed(accountURN+":comments", {
name: "Flickr Comments",
URL: gStrings["commentsreceivedRSS"].replace("%accountid%", aAccountID),
favicon: FLICKR_FAVICON,
serviceId: "@flock.com/feed-manager;1"
});
account.children.addOnce(commentstream);
var replystream = new this.faves_coop.Feed(accountURN+":replies", {
name: "Flickr Replies",
URL: gStrings["commentrepliesRSS"].replace("%accountid%", aAccountID),
favicon: FLICKR_FAVICON,
serviceId: "@flock.com/feed-manager;1"
});
account.children.addOnce(replystream);
****************/
this.updateActions(accountURN);
// Instanciate account component
var acct = this.getAccount(account.id());
if (aListener) aListener.onSuccess(acct, "addAccount");
return acct;
}
// END flockIWebService interface
// BEGIN flockIAuthenticateNewAccount interface
flickrService.prototype.authenticateNewAccount =
function flickrService_authenticateNewAccount(aListener)
{
this._logger.info("{flockIAuthenticateNewAccount}.authenticateNewAccount(aListener)");
aListener.onStart(null, "newaccountstarted");
var inst = this;
var frobListener = {
onResult: function (aXML) {
inst._logger.info(".authenticateNewAccount(): frobListener: onResult()");
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Components.interfaces.nsIWindowWatcher);
var topWin = wm.getMostRecentWindow(null);
var frob = aXML.getElementsByTagName("frob")[0].firstChild.nodeValue;
var authURL = inst.api.getAuthUrl(frob, "write");
var url = "chrome://browser/content/flock/photo/photoLoginWindow.xul?"
+ "url="+escape(authURL)+"&finalString=logout.gne";
var chrome = "chrome,close,titlebar,resizable=yes,toolbar,dialog=no,"
+ "scrollbars=yes,modal,centerscreen";
topWin.open(url, "_blank", chrome);
var acctURN = inst.acUtils.getFirstAuthenticatedAccountForService(FLICKR_CONTRACTID);
var account = null;
try {
account = inst.getAccount(acctURN);
if (!account) throw "ACCOUNT WAS NOT CREATED";
} catch (ex) {
inst._logger.info(".authenticateNewAccount(): frobListener: onResult(): ERROR: account was not created");
if (aListener) aListener.onError(ex);
}
if (aListener) aListener.onSuccess(account, "", null);
},
onError: function (aError) {
inst._logger.info(".authenticateNewAccount(): frobListener: onError()");
if (aListener) aListener.onError(aError);
}
};
this.api.call(frobListener, "flickr.auth.getFrob", null);
}
// END flockIAuthenticateNewAccount
// BEGIN flockIManageableWebService interface
flickrService.prototype.updateAccountStatusFromDocument =
function flickrService_updateAccountStatusFromDocument(aDocument)
{
this._logger.info("{flockIManageableWebService}.updateAccountStatusFromDocument()");
if (this.webDetective.detect("flickr", "loggedout", aDocument, null))
{
this.acUtils.markAllAccountsAsLoggedOut(FLICKR_CONTRACTID);
// Also de-authenticate the API
this.api.logout();
this.state = flockIPhotoAPI.LOGGED_OUT;
flock_refreshMediabarIfHasPrivate()
} else if (this.webDetective.detect("flickr", "loggedin", aDocument, null)) {
var results = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
if (this.webDetective.detect("flickr", "accountinfo", aDocument, results)) {
var accountID = results.getPropertyAsAString("accountid");
if (accountID && accountID.length) {
var accountURN = this.acUtils.getAccountURNById(this.urn, accountID);
var acct = this.faves_coop.get(accountURN);
var username = results.getPropertyAsAString("username");
if (username && username.length) {
acct.name = username;
}
var avatarURL = results.getPropertyAsAString("avatarURL");
if (avatarURL && avatarURL.length) {
acct.avatar = avatarURL;
}
if (!acct.isAuthenticated) {
var inst = this;
var loginListener = {
onAuth: function () {
inst._logger.info(".updateAccountStatusFromDocument(): loginListener: onAuth()");
},
onError: function (aError) {
inst._logger.info(".updateAccountStatusFromDocument(): loginListener: onError()");
inst._logger.info(aError ? (aError.errorString) : "No details");
acct.isAuthenticated = false;
}
};
this.login(accountURN, loginListener);
// I'm going to somewhat prematurely assume that the authentication
// will succeed. If it fails, the listener will catch it.
acct.isAuthenticated = true;
}
}
}
}
}
// END flockIManageableWebService interface
// BEGIN flockISocialWebService interface
flickrService.prototype.decorateForPerson =
function flickrService_decorateForPerson(aDocument)
{
this._logger.info("{flockISocialWebService}.decorateForPerson()");
}
flickrService.prototype.browseFriends =
function flickrService_browseFriends(aFriendURN, aListener)
{
this._logger.info("{flockISocialWebService}.browseFriends('"+aFriendURN+"')");
var inst = this;
if (this.foafController) {
this.foafController.cancelMe();
}
if (!aFriendURN) return;
var friend = this.faves_coop.get(aFriendURN);
if (!friend) {
aListener.onError(null, "notAContact");
return;
}
var contactListener = {
onGetContactsResult: function(enum_) {
var lister = this;
function myWorker(shouldYield) {
var count = 0;
while (enum_.hasMoreElements()) {
if (lister.cancel) return;
var person = enum_.getNext();
count++;
inst.addFoafPerson(person, aFriendURN);
if (count % 3 == 0 && shouldYield()) yield;
}
aListener.onSuccess(enum_, "success");
}
getCompTK().schedule(gTimers, 0.4, 40, myWorker);
},
onError: function() {
inst._logger.info("JMC: uhoh....");
},
cancelMe: function() {
this.cancel = true;
}
};
this.foafController = contactListener;
this.getFriendsContacts(contactListener, friend.accountId);
}
// END flockISocialWebService interface
// BEGIN flockIMediaWebService interface
flickrService.prototype.decorateForMedia =
function flickrService_decorateForMedia(aDocument)
{
this._logger.info("{flockIMediaWebService}.decorateForMedia(aDocument)");
var results = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
var mediaArr = [];
if (this.webDetective.detect("flickr", "person", aDocument, results)) {
var media = {
name: results.getPropertyAsAString("username"),
query: "user:" + results.getPropertyAsAString("userid") + "|username:" + results.getPropertyAsAString("username"),
label: results.getPropertyAsAString("username"),
favicon: this.icon,
service: this.shortName
}
mediaArr.push(media);
}
if (this.webDetective.detect("flickr", "pool", aDocument, results)) {
var media = {
name: results.getPropertyAsAString("groupname"),
query: "pool:" + results.getPropertyAsAString("groupid") + "|albumlabel:" + results.getPropertyAsAString("groupname"),
label: results.getPropertyAsAString("groupname"),
favicon: this.icon,
service: this.shortName
}
mediaArr.push(media);
}
if (mediaArr.length > 0) {
if (!aDocument._flock_decorations) {
aDocument._flock_decorations = {};
}
aDocument._flock_decorations.mediaArr = mediaArr;
this.obs.notifyObservers(aDocument, "media", "media:update");
}
}
flickrService.prototype.handlesMediaStream =
function flickrService_handlesMediaStream()
{
return true;
}
flickrService.prototype.checkIsStreamUrl =
function flickrService_checkIsStreamUrl(aUrl)
{
this._logger.debug("Checking if url is flickr stream: " + aUrl);
if (aUrl.match(/^https?:\/\/([^\/]*\.)?flickr\.com\/photos\/upload($|\/)/) ||
aUrl.match(/^https?:\/\/([^\/]*\.)?flickr\.com\/photos\/organize($|\/)/) ||
aUrl.match(/^https?:\/\/([^\/]*\.)?flickr\.com\/photos\/tags($|\/)/) ||
aUrl.match(/^https?:\/\/([^\/]*\.)?flickr\.com\/photos\/search($|\/)/) ||
aUrl.match(/^https?:\/\/[^\.]*\.?flickr\.com\/photos\/([^\/]+)\/.+/) ||
aUrl.match(/^https?:\/\/farm\d*\.static\.flickr\.com\/.*/) ) {
return true;
}
return false;
}
flickrService.prototype.getMediaQueryFromURL =
function flickrService_getMediaQueryFromURL(aUrl, aListener)
{
var myListener = {
onResult:function (aXML) {
try {
var results = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
var userID = aXML.getElementsByTagName('user')[0].getAttribute('id');
var userName = aXML.getElementsByTagName('username')[0].firstChild.nodeValue;
results.setPropertyAsAString("query", "user:" + userID + "|username:" + userName);
results.setPropertyAsAString("title", userName);
aListener.onSuccess(results, "query");
} catch (ex) {
aListener.onError(null, "Unable to get user.", null);
}
},
onError: function (aError) {
aListener.onError(null, aError.errorString, null);
}
}
this._logger.debug("Finding User ID from Url: " + aUrl);
var params = {};
params.url = aUrl
var dict = params2Dictionary(params);
this.call(myListener, "flickr.urls.lookupUser", dict);
}
// END flockIMediaWebService
// ========== END flickrService class ==========
// ================================================
// ========== BEGIN XPCOM Module support ==========
// ================================================
function createModule(aParams) {
return {
registerSelf: function (aCompMgr, aFileSpec, aLocation, aType) {
aCompMgr.QueryInterface(Ci.nsIComponentRegistrar);
aCompMgr.registerFactoryLocation( aParams.CID, aParams.componentName,
aParams.contractID, aFileSpec,
aLocation, aType );
var catMgr = Cc["@mozilla.org/categorymanager;1"]
.getService(Ci.nsICategoryManager);
if (!aParams.categories) { aParams.categories = []; }
for (var i = 0; i < aParams.categories.length; i++) {
var cat = aParams.categories[i];
catMgr.addCategoryEntry( cat.category, cat.entry,
cat.value, true, true );
}
},
getClassObject: function (aCompMgr, aCID, aIID) {
if (!aCID.equals(aParams.CID)) { throw Cr.NS_ERROR_NO_INTERFACE; }
if (!aIID.equals(Ci.nsIFactory)) { throw Cr.NS_ERROR_NOT_IMPLEMENTED; }
return { // Factory
createInstance: function (aOuter, aIID) {
if (aOuter != null) { throw Cr.NS_ERROR_NO_AGGREGATION; }
var comp = new aParams.componentClass();
if (aParams.implementationFunc) { aParams.implementationFunc(comp); }
return comp.QueryInterface(aIID);
}
};
},
canUnload: function (aCompMgr) { return true; }
};
}
// NS Module entrypoint
function NSGetModule(aCompMgr, aFileSpec) {
return createModule({
componentClass: flickrService,
CID: FLICKR_CID,
contractID: FLICKR_CONTRACTID,
componentName: CATEGORY_COMPONENT_NAME,
implementationFunc: function (aComp) { getCompTK().addAllInterfaces(aComp); },
categories: [
{ category: "wsm-startup", entry: CATEGORY_COMPONENT_NAME, value: FLICKR_CONTRACTID },
{ category: "flockIPhotoAPI", entry: CATEGORY_ENTRY_NAME, value: FLICKR_CONTRACTID },
{ category: "flockWebService", entry: CATEGORY_ENTRY_NAME, value: FLICKR_CONTRACTID }
]
});
}
// ========== END XPCOM Module support ==========
// =============================================
// ========== BEGIN MultiGetter class ==========
// =============================================
function MultiGetter() {
}
MultiGetter.prototype = {
mTimer: Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer),
init: function(aSvc, aListener, aEnumerator) {
this.mHasNew = false;
this.mNeedSave = false;
this.mSvc = aSvc;
this.mListener = aListener;
this.mArray = [];
this.mMap = {};
while (aEnumerator.hasMoreElements()) {
var p = aEnumerator.getNext();
p.QueryInterface(Components.interfaces.flockIPhotoPerson);
this.mMap[p.id] = p;
this.mArray.push(p.id);
//this._logger.info(p + " " + p.id + " " + this.mArray.length + " initting \n");
}
if (this.mSvc.isLoggedIn) {
this.doBiggee();
}
else {
this.next();
}
},
updatePerson: function(aPerson, aPhoto) {
//this._logger.info(aPerson.username + "updating person\n");
var seq = aPerson.seq;
var newSeq = parseInt(aPhoto.id);
if (newSeq > seq) {
var oldHasNew = aPerson.hasNew;
aPerson.seq = aPhoto.id;
this.mNeedSave = true;
if (seq != 0) {
this.mHasNew = true;
aPerson.hasNew = true
if (oldHasNew == false) {
aPerson.lastNewSeq = seq + 1;
}
}
}
this.mMap[aPerson.id] = null;// wipe this entry out
},
doBiggee: function() {
var inst = this;
var listener = {
onSearchResult: function(aEnumerator) {
//this._logger.info("on search result\n");
try {
while (aEnumerator.hasMoreElements()) {
var photo = aEnumerator.getNext();
var person = inst.mMap[photo.userid]; // username is actuall an id
//this._logger.info("result\n")
if (!person) continue;
inst.updatePerson(person, photo);
}
} catch(e) {
//this._logger.info("this" + e + " " + e.lineNumber + "\n");
}
inst.next();
},
onError: function(aError) {
//this._logger.info("on error result\n");
//hmm. mebbe should bail
inst.finish();
}
}
this.mSvc.getContactsPhotos(listener);
},
finish: function() {
//this._logger.info("FINITI\n");
if (this.mHasNew) {
this.mListener.onGetMostRecentPhotoForList(Components.interfaces.flockIPhotoAPIListener.LIST_HAS_NEW);
}
else if (this.mNeedSave) {
this.mListener.onGetMostRecentPhotoForList(Components.interfaces.flockIPhotoAPIListener.LIST_NEED_SAVE);
}
else {
this.mListener.onGetMostRecentPhotoForList(Components.interfaces.flockIPhotoAPIListener.LIST_NO_CHANGE);
}
return;
},
notify: function() {
this.doNext();
},
next: function() {
this.mTimer.initWithCallback(this, 1000, 0);
},
doNext: function() {
//this._logger.info("NEXT PLEASE\n");
var inst = this;
var person = null;
for (;;) {
if (!this.mArray.length) break;
var id = this.mArray.pop();
//this._logger.info(id + " " + "< NEXT PLEASE\n");
person = this.mMap[id];
if (person) {
break;
}
}
if (!person) {
this.finish();
return;
}
var listener = {
onSearchResult: function(aEnumerator) {
//this._logger.info("b search result\n");
while (aEnumerator.hasMoreElements()) {
var photo = aEnumerator.getNext();
var person = inst.mMap[photo.userid]; // username is actuall an id
inst.updatePerson(person, photo);
break;
}
inst.next();
},
onError: function(aError) {
//this._logger.info("b search eror\n");
inst.finish();
}
}
this.mSvc.search(listener, person.id, "", "", 1, 1);
}
}
// ========== END MultiGetter class ==========
// ===========================================
// ========== BEGIN FlickrAPI class ==========
// ===========================================
function FlickrAPI() {
this._logger = Components.classes['@flock.com/logger;1'].createInstance(Components.interfaces.flockILogger);
this._logger.init('flickrAPI');
this._logger.info('Created Flickr API Object');
var inst = this;
this.need2CreateAlbum = false;
this.api_key = "92c2a562f0e9c2ed8dfe78f42a7734c7";
this.api_secret = "17b26c20558cf979";
this.endpoint = "http://www.flickr.com/services/rest/";
this.upload_endpoint = "http://www.flickr.com/services/upload/";
this.auth_endpoint = "http://www.flickr.com/services/auth/";
this.req = null;
this.frob = null;
this.lastToken = new Date();
this.authUser = null;
this.filesToDelete = [];
this.setEndpoint = function(aEndpoint) {
this.endpoint = aEndpoint;
};
this.reset = function() {
this.hasCreateAlbum = null;
};
this.getAuthUser = function() {
return this.authUser;
};
this.getStoredToken = function(aListener) {
};
this.checkToken = function(aListener, aToken) {
var tokenListener = {
onResult: function (aXML) {
var flickrUser = new FlickrUser();
flickrUser.token = aXML.getElementsByTagName("token")[0].firstChild.nodeValue;
var user = aXML.getElementsByTagName("user")[0];
flickrUser.nsid = user.getAttribute("nsid");
flickrUser.id = user.getAttribute("nsid");
flickrUser.username = user.getAttribute("username");
flickrUser.fullname = user.getAttribute("fullname");
inst.authUser = flickrUser;
inst._logger.info("token checks out");
inst.lastToken = new Date();
aListener.onAuth();
},
onError: function (aError) {
inst._logger.info("Token does not pass muster");
inst.frob = null;
aListener.onError(null);
}
}
var token = aToken;
var params = {
auth_token: token
};
this.call(tokenListener, "flickr.auth.checkToken", params);
};
this.getToken = function(aAccountURN, aListener) {
inst._logger.info("entering getToken");
var acctCoopObj = this.svc.faves_coop.get(aAccountURN);
var flickrUser = new FlickrUser();
// we have an existing token, let's see if it's valid
if (acctCoopObj.authToken && acctCoopObj.authToken.length) {
var checkTokenListener = {
onAuth : function() {
// the token is aiighttt lets reuse it
inst._reuseToken(aAccountURN, aListener);
},
onError: function(aError) {
// something
inst._getNewToken(aAccountURN, aListener);
}
};
this.checkToken(checkTokenListener, acctCoopObj.authToken);
} else {
this._getNewToken(aAccountURN, aListener);
}
};
this._reuseToken = function(aAccountURN, aListener) {
inst._logger.info("entering _reuseToken");
var acctCoopObj = inst.svc.faves_coop.get(aAccountURN);
var flickrUser = new FlickrUser();
flickrUser.token = acctCoopObj.authToken;
flickrUser.nsid = acctCoopObj.flickr_nsid;
flickrUser.id = acctCoopObj.flickr_id;
flickrUser.username = acctCoopObj.flickr_username;
flickrUser.fullname = acctCoopObj.flickr_fullname;
this.authUser = flickrUser;
inst.svc.acUtils.ensureOnlyAuthenticatedAccount(aAccountURN);
};
this._getNewToken = function(aAccountURN, aListener, aFrob) {
inst._logger.info("entering _getNewToken");
var acctCoopObj = inst.svc.faves_coop.get(aAccountURN);
var flickrUser = new FlickrUser();
var tokenListener = {
onResult: function (aXML) {
flickrUser.token = aXML.getElementsByTagName("token")[0].firstChild.nodeValue;
var user = aXML.getElementsByTagName("user")[0];
flickrUser.nsid = user.getAttribute("nsid");
flickrUser.id = user.getAttribute("nsid");
flickrUser.username = user.getAttribute("username");
flickrUser.fullname = user.getAttribute("fullname");
inst.authUser = flickrUser;
acctCoopObj.authToken = flickrUser.token;
acctCoopObj.flickr_nsid = flickrUser.nsid;
acctCoopObj.flickr_id = flickrUser.id;
acctCoopObj.flickr_username = flickrUser.username;
acctCoopObj.flickr_fullname = flickrUser.fullname;
inst.svc.acUtils.ensureOnlyAuthenticatedAccount(aAccountURN);
inst._logger.info("got token");
this.lastToken = new Date();
aListener.onAuth();
},
onError: function (aError) {
inst._logger.info("error getting token");
this.frob = null;
if (!aError.errorCode) aError.errorCode = 1002;
aListener.onError(aError);
}
}
var frob = aFrob;
if (!frob) {
frob = this.frob;
}
var params = {
frob: frob
};
this.call(tokenListener, "flickr.auth.getToken", params);
},
this.isLoggedIn = function() {
if (this.authUser) return true;
return false;
};
this.logout = function() {
this.authUser = null;
this.frob = null;
this.token = null;
flock_refreshMediabarIfHasPrivate()
};
this.login = function(aAccountURN, aListener) {
inst._logger.info("api.login('"+aAccountURN+"')");
this.authUser = null;
this.frob = null;
var api = this;
// for http://bugzilla.flock.com/show_bug.cgi?id=6255 --
// ensure that the frob and auth token synch up
if (0 /*acctCoopObj.authToken && acctCoopObj.authToken.length*/) {
inst._logger.info("api.login('"+aAccountURN+"'): trying to reuse token");
var reuseTokenListener = {
onResult: function (aXML) {
inst._logger.info("api.login('"+aAccountURN+"') reuseTokenListener: onResult()");
aListener.onAuth();
},
onError: function (aError) {
inst._logger.info("api.login('"+aAccountURN+"') reuseTokenListener: onError()");
aListener.onError(aError);
}
};
this.getToken(aAccountURN, reuseTokenListener);
} else {
// get new frob
inst._logger.info("api.login('"+aAccountURN+"'): need new token");
var frobListener = {
onResult: function (aXML) {
try {
var frobNode = aXML.getElementsByTagName("frob")[0];
var frob = frobNode.firstChild.nodeValue;
var authUrl = api.getAuthUrl(frob, "write");
inst.frob = frob;
api.frob = frob;
var hr = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1']
.createInstance(Components.interfaces.nsIXMLHttpRequest);
var onReadyStateFunc = function (eEvt) {
if (hr.readyState == 4) {
if (api.svc.webDetective.detectNoDOM("flickr", "apiAuth2", "", hr.responseText, null)) {
inst._logger.info("Successfully authorized2!");
api._getNewToken(aAccountURN, aListener, frob);
} else {
var results = Components.classes["@mozilla.org/hash-property-bag;1"]
.createInstance(Components.interfaces.nsIWritablePropertyBag2);
//dump("CDC: apiAuth1: "+hr.responseText+"\n");
if (api.svc.webDetective.detectNoDOM("flickr", "apiAuth1", "", hr.responseText, results)) {
var hr2 = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Components.interfaces.nsIXMLHttpRequest);
var postBody = "magic_cookie=" + results.getPropertyAsAString("magic_cookie")
+ "&api_key=" + api.api_key
+ "&api_sig=" + results.getPropertyAsAString("api_sig")
+ "&perms=write"
+ "&frob=" + frob
+ "&done_auth=1";
hr2.onreadystatechange = function (eEvt2) {
if (hr2.readyState == 4) {
if (api.svc.webDetective.detectNoDOM("flickr", "apiAuth2", "", hr2.responseText, null)) {
inst._logger.info("Successfully authorized!");
api._getNewToken(aAccountURN, aListener, frob);
} else {
inst._logger.info("NOT successfully authorized!");
inst._logger.info(hr2.responseText);
aListener.onError(null);
}
}
}
hr2.detachLoadGroup = true;
hr2.overrideMimeType("text/txt");
hr2.open("POST", "http://www.flickr.com/services/auth/");
hr2.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
hr2.send(postBody);
} else if (api.svc.webDetective.detectNoDOM("flickr", "apiAuth3", "", hr.responseText, null)) {
inst._logger.info("Successfully authorized with apiAuth3!");
api._getNewToken(aAccountURN, aListener, frob);
} else {
inst._logger.debug("Error - did not detect apiAuth1 or apiAuth3");
aListener.onError(null);
}
}
}
};
hr.onreadystatechange = onReadyStateFunc;
hr.detachLoadGroup = true;
hr.overrideMimeType("text/txt");
hr.open("GET", authUrl,true);
hr.send(null);
//var topWindow = windowManagerInterface.getMostRecentWindow(null);
//var url = "chrome://browser/content/flock/photo/photoLoginWindow.xul?"+"url="+escape(authUrl)+"&finalString=logout.gne";
//topWindow.open(url,"_blank", "chrome,close,titlebar,resizable=yes,toolbar,dialog=no,scrollbars=yes,modal,centerscreen");
}
catch(e) {
inst._logger.info("caught this one in login: " + e);
}
},
onError: function (aError) {
inst._logger.debug("There was an error getting the frob.");
aListener.onError(aError);
}
};
this.call(frobListener, "flickr.auth.getFrob", null);
}
};
this.add2Album = function(aUploadListener, aUpload, aID) {
var inst = this;
var listener = {
onResult: function(aXML) {
inst.finalizePhoto(aUploadListener, aUpload, aID);
},
onError: function(aError) {
inst.finalizePhoto(aUploadListener, aUpload, aID);
}
}
var params = {};
params.photoset_id = aUpload.album;
params.photo_id = aID;
this.authenticatedCall(listener, "flickr.photosets.addPhoto", params);
};
/*
this.createAlbum = function(aUploadListener, aUpload, aID) {
var inst = this;
var listener = {
onCreateAlbumResult: function(aAlbum) {
},
onError: function(aError) {
},
}
var params = {};
params.photoset_id = aUpload.album;
params.photo_id = aID;
this.svc.reallyCreateAlbum(listener, call(listener, "flickr.photosets.addPhoto", params));
};
*/
this.finalizePhoto = function(aUploadListener, aUpload, aID) {
try {
var inst = this;
var getPhotoListener = {
onGetPhotoResult: function(aPhoto) {
aUploadListener.onUploadFinalized(aUpload, aPhoto);
},
onError: function(aError) {
aUploadListener.onError(null);
}
}
inst.svc.getPhoto(getPhotoListener, aID);
} catch(e) {
inst._logger.info(e);
}
};
this.mAddingAlbums = false;
this.mPhotos2Album = [];
this.processPendingAlbumAdditions = function() {
if (this.mAddingAlbums) return;
if (this.mPhotos2Album.length == 0) return;
this.mAddingAlbums = true;
var obj = this.mPhotos2Album[0];
var photoid = obj.photoid;
var albumid = obj.albumid;
var inst = this;
if (this.svc.fakeAlbums[albumid] && !this.svc.realishAlbums[albumid]) {
var listener = {
onCreateAlbumResult: function(aAlbum) {
inst.svc.realishAlbums[albumid] = aAlbum.id;
inst.mAddingAlbums = false;
},
onError: function(aError) {
inst.mAddingAlbums = false;
}
}
// var params = {};
// params.photoset_id = photoid;
// params.photo_id = albumid;
var fakeAlbum = this.svc.fakeAlbums[albumid];
this.svc.reallyCreateAlbum(listener, fakeAlbum.title, photoid);
}
else {
if (inst.svc.realishAlbums[albumid]) {
albumid = inst.svc.realishAlbums[albumid];
}
var listener = {
onResult: function(aXML) {
inst.finalizePhoto(obj.listener, obj.upload, photoid);
inst.mPhotos2Album.shift();
inst.mAddingAlbums = false;
inst.processPendingAlbumAdditions();
//re-enter to optimize
},
onError: function(aError) {
inst.finalizePhoto(obj.listener, obj.upload, photoid);
inst.mPhotos2Album.shift();
inst.mAddingAlbums = false;
//re-enter to optimize?? this is an error condition, por
//supuesto
}
}
var params = {};
params.photoset_id = albumid;
params.photo_id = photoid;
this.authenticatedCall(listener, "flickr.photosets.addPhoto", params);
}
};
this.mCheckTicketsInProcess = false;
this.processPendingUploadTickets = function() {
if (this.mCheckTicketsInProcess) return;
var ticketList = "";
for (var p in this.mPendingTickets) {
var obj = this.mPendingTickets[p];
if (!obj) continue;//really should be removeing these - make it an array?
ticketList += obj.ticketid + ",";
}
if (ticketList.length == 0) return;
this.mCheckTicketsInProcess = true;
var params = {
tickets: ticketList
};
var inst = this;
var ticketListener = {
onResult: function (aXML) {
inst.mCheckTicketsInProcess = false;
var ticketList = aXML.getElementsByTagName("ticket");
for (var i = 0; i < ticketList.length; i++) {
var ticket = ticketList[i];
var id = ticket.getAttribute("id");
var photoid = ticket.getAttribute("photoid");
var complete = ticket.getAttribute("complete");
var invalid = ticket.getAttribute("invalid");
var obj = inst.mPendingTickets[id];
if (complete =="0") {
continue;
}
else if (invalid) {
obj.listener.onError(null);
}
else if (complete =="1") {
if (obj.upload.album && obj.upload.album.length>0) {
obj.photoid = photoid;
obj.albumid = obj.upload.album;
obj.listener = obj.listener;
inst.mPhotos2Album.push(obj);
}
else {
inst.finalizePhoto(obj.listener, obj.upload, photoid);
}
}
else if (complete =="2") {
obj.listener.onError(null);
}
inst.mPendingTickets[id] = null;//that doesn't really remove it tho
}
},
onError: function (aXML) {
inst.mCheckTicketsInProcess = false;
}
}
this.call(ticketListener, "flickr.photos.upload.checkTickets", params);
};
this.mPendingTickets = {};
this.upload = function(aListener, aPhoto, aParams, aUpload) {
var inst = this;
this.uploader = new PhotoUploader();
var myListener = {
onResult: function(aXML) {
var rsp = aXML.getElementsByTagName("rsp")[0];
var stat = rsp.getAttribute("stat");
if (stat !="ok") {
var err = aXML.getElementsByTagName("err")[0];
var error= inst.getError('SERVICE_ERROR', aXML, null);
aListener.onError(error);
}
else {
aListener.onUploadComplete(aUpload);
var ticketid = aXML.getElementsByTagName("ticketid")[0].firstChild.nodeValue;
inst._logger.info(ticketid + "pre ticketid");
inst.mPendingTickets[ticketid] = {
ticketid: ticketid,
upload: aUpload,
listener: aListener
}
inst._logger.info(ticketid + "post ticketid");
/*
if (aUpload.album && aUpload.album.length>0) {
var ticketid = aXML.getElementsByTagName("ticketid")[0].firstChild.nodeValue;
inst.mPendingTickets[ticketid] = {
ticketid: ticketid,
upload: aUpload,
listener: aListener,
}
}
else {
aListener.onUploadFinalized(aUpload, null);
}
*/
}
},
onError: function(aErrorCode) {
if (aErrorCode) {
aListener.onError(inst.getError('HTTP_ERROR', null, aErrorCode));
} else {
aListener.onError(inst.getError('SERVICE_ERROR', null));
}
},
onProgress: function(aCurrentProgress) {
aListener.onProgress(aCurrentProgress);
}
}
this.convertBools(aParams);
this.convertTags(aParams);
aParams.auth_token = this.authUser.token;
aParams.api_key = this.api_key;
aParams = this.appendSignature(aParams);
this.uploader.setEndpoint(this.upload_endpoint);
this.uploader.upload(myListener, aPhoto, aParams);
return;
};
this.convertBools = function(aParams) {
for (var p in aParams) {
if (!p.match(/^is/)) continue;
// I hope that this doesn't break anything
if (aParams[p]=="true") aParams[p] = "1";
if (aParams[p]=="false") aParams[p] = "0";
}
};
this.convertTags = function(aParams) {
for (var p in aParams) {
if (p != "tags") continue;
var tags = aParams[p].split(",");
for (var i = 0; i < tags.length;++i) {
tags[i] = '"' + tags[i] + '"';
tags[i] = tags[i].replace(/\"+/g,'"');
}
aParams[p] = tags.join(",");
}
};
this.authenticatedCall = function(aListener, aMethod, aParams) {
if (!aParams) aParams = {};
aParams.auth_token = this.authUser.token;
this.call(aListener, aMethod, aParams);
var paramString = this.getParamString(aParams, true);
};
this.call = function(aListener, aMethod, aParams) {
this.convertBools(aParams);
this.convertTags(aParams);
if (aParams == null) aParams = [];
if (aMethod) aParams.method = aMethod;
aParams.api_key = this.api_key;
var paramString = this.getParamString(aParams, (aMethod == null));
var url = this.endpoint + "?" + paramString;
this._doCall(aListener, url, null);
};
this._doCall = function(aListener, aUrl, aContent) {
inst._logger.info("Sending " + aUrl);
this.req = Components.classes['@mozilla.org/xmlextras/xmlhttprequest;1']
.createInstance(Components.interfaces.nsIXMLHttpRequest);
this.req.QueryInterface(Components.interfaces.nsIJSXMLHttpRequest);
this.req.open('GET', aUrl, true);
var req = this.req;
this.req.onreadystatechange = function (aEvt) {
if (req.readyState == 4) {
try {
if (req.status/100 == 2) {
try {
//inst._logger.info(req.responseText);
var rsp = req.responseXML.getElementsByTagName("rsp")[0];
var stat = rsp.getAttribute("stat");
if (stat !="ok") {
var err = req.responseXML.getElementsByTagName("err")[0];
var error= inst.getError('SERVICE_ERROR', req.responseXML, null);
aListener.onError(error);
}
else {
aListener.onResult(req.responseXML);
}
} catch (ex) {
// error parsing xml
inst._logger.info(ex);
aListener.onError(inst.getError('SERVICE_ERROR', null, null));
}
}
else {
// http errors
aListener.onError(inst.getError("HTTP_ERROR", null, req.status));
}
} catch(e) {
// XMHTTPERROR (connection lost)
inst._logger.info(e);
aListener.onError(inst.getError('HTTP_ERROR',null, "9001"));
}
}
}
this.req.send(null);
};
this.getError = function(aErrorType, aXML, aHTTPErrorCode) {
var error = Components.classes[FLOCK_ERROR_CONTRACTID].createInstance(flockIError);
if (aErrorType == "HTTP_ERROR") {
error.errorCode = aHTTPErrorCode;
} else if (aErrorType == "SERVICE_ERROR") {
var errorCode;
var errorMessage;
var serviceErrorMessage;
try {
errorCode = aXML.getElementsByTagName("err")[0].getAttribute('code');
serviceErrorMessage = aXML.getElementsByTagName("err")[0].getAttribute('msg');
} catch (ex) {
errorCode = "999" // in case the error xml is invalid
}
switch (errorCode) {
case "1":
error.errorCode = error.PHOTOSERVICE_INVALID_USER;
break;
case "3":
error.errorCode = error.PHOTOSERVICE_UPLOAD_ERROR;
break;
case "4":
error.errorCode = error.PHOTOSERVICE_FILE_IS_OVER_SIZE_LIMIT;
break;
case "5":
error.errorCode = error.PHOTOSERVICE_INVALID_UPLOAD_FILE;
break;
case "6":
error.errorCode = error.PHOTOSERVICE_BANDWIDTH_REACHED;
break;
case "10":
break;
case "98":
error.errorCode = error.PHOTOSERVICE_LOGIN_FAILED;
break;
case "99":
error.errorCode = error.PHOTOSERVICE_USER_NOT_LOGGED_IN;
break;
case "100":
error.errorCode = error.PHOTOSERVICE_INVALID_API_KEY;
break;
case "105":
error.errorCode = error.PHOTOSERVICE_UNAVAILABLE;
break;
case "999":
error.errorCode = error.PHOTOSERVICE_UNKNOWN_ERROR;
break;
default:
error.errorCode = error.PHOTOSERVICE_UNKNOWN_ERROR;
error.serviceErrorString = serviceErrorMessage;
break;
}
}
//inst._logger.info('<<<<<<<<<<<<<<' + error.errorString + '\n');
return error;
};
this.getAuthUrl = function(aFrob, aPerms) {
var api_key = this.api_key;
var params = {
api_key: api_key,
perms: aPerms,
frob: aFrob
}
var paramString = this.getParamString(params, true);
return this.auth_endpoint + "?" + paramString;
};
this.getParamString = function(aParams, aNoMethod) {
aParams = this.appendSignature(aParams);
var rval = "";
if (!aNoMethod) rval += "method=" + aParams.method + "&";
var count = 0;
for (var p in aParams) {
if (p.match(/method/)) continue;
if (count++ != 0) rval += "&";
rval += encodeURIComponent(p) + "=" + encodeURIComponent(aParams[p]);
}
return rval;
};
this.appendSignature = function(aParams) {
var keys = [];
for (var p in aParams) {
keys.push(p);
}
keys.sort();
var preHash = this.api_secret;
for (var i = 0; i < keys.length; ++i) {
preHash += keys[i] + aParams[keys[i]];
}
inst._logger.info("preHash " + preHash);
var converter =
Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
.createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
var inputStream = converter.convertToInputStream(preHash);
aParams.api_sig = hex_md5_stream(inputStream);
return aParams;
};
}
FlickrAPI.prototype = {};
// ========== END FlickrAPI class ==========
// ============================================
// ========== BEGIN FlickrUser class ==========
// ============================================
function FlickrUser() {
this.token = "";
this.perms = "";
this.nsid = "";
this.id = "";
this.username = "";
this.fullname = "";
}
FlickrUser.prototype = {};
// ========== END FlickrUser class =========
// ===============================================
// ========== BEGIN flickrAccount class ==========
// ===============================================
function flickrAccount()
{
this._logger = Components.classes['@flock.com/logger;1'].createInstance(Components.interfaces.flockILogger);
this._logger.init('flickrAccount');
this._logger.info('Created Flickr Account Object');
this.acUtils = Components.classes["@flock.com/account-utils;1"]
.getService(Components.interfaces.flockIAccountUtils);
this.photoAPI = Components.classes[FLICKR_CONTRACTID]
.getService(Components.interfaces.flockIPhotoAPI)
.QueryInterface(Components.interfaces.flockIWebService);
this._coop = Components.classes["@flock.com/singleton;1"]
.getService(Components.interfaces.flockISingleton)
.getSingleton("chrome://browser/content/flock/common/load-faves-coop.js")
.wrappedJSObject;
this._ctk = {
interfaces: [
"nsISupports",
"flockIWebServiceAccount",
"flockISocialWebServiceAccount",
"flockIMediaWebServiceAccount",
"flockIMediaUploadAccount",
]
};
getCompTK().addAllInterfaces(this);
}
// BEGIN flockIWebServiceAccount interface
flickrAccount.prototype.urn = null;
flickrAccount.prototype.login =
function flickrAccount_login(aListener)
{
this._logger.info("{flockIWebServiceAccount}.login()");
this.photoAPI.login(this.urn, aListener);
}
flickrAccount.prototype.logout =
function flickrAccount_logout(aListener)
{
this._logger.info("{flockIWebServiceAccount}.logout()");
var acctCoopObj = this._coop.get(this.urn);
if (acctCoopObj.isAuthenticated) {
acctCoopObj.isAuthenticated = false;
this.photoAPI.logout();
}
}
flickrAccount.prototype.activate =
function flickrAccount_activate(aListener)
{
this._logger.info("{flockIWebServiceAccount}.activate()");
var acctCoopObj = this._coop.get(this.urn);
var inst = this;
var listener = {
onAuth: function () {
if (aListener) aListener.onSuccess(inst, "accountAuthorized");
acctCoopObj.isPollable = true;
//acctCoopObj.isAuthenticated = true;
inst.acUtils.ensureOnlyAuthenticatedAccount(inst.urn);
//inst.acUtils.makeTempPasswordPermanent(inst.photoAPI.urn+':'+acctCoopObj.accountId);
},
onError: function (aError) {
inst._logger.info( "Flickr account activation ERROR: " +
(aError ? aError.errorString : "No details. :("));
acctCoopObj.isAuthenticated = false;
}
};
this.photoAPI.login(this.urn, listener);
// I'm going to jump the gun a bit here and assume that the authentication is
// going to succeed. If it fails, it will be caught by the listener. But at
// least this will prevent any further attempts to authenticate until this
// attempt completes.
acctCoopObj.isAuthenticated = true;
}
// END flockIWebServiceAccount interface
// BEGIN flockISocialWebServiceAccount interface
flickrAccount.prototype.browseFriends =
function flickrAccount_browseFriends(aFriendURN, aListener)
{
this._logger.info("{flockISocialWebServiceAccount}.browseFriends('"+aFriendURN+"')");
this.service.browseFriends(aFriendURN, aListener);
}
// END flockISocialWebServiceAccount interface
// ========== END flickrAccount class ==========